import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutterlib/common/config/config.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import 'pull_load_widget.dart';

mixin PullLoadListState<T extends StatefulWidget>
    on State<T>, AutomaticKeepAliveClientMixin<T> {
  bool isShow = false;

  bool isLoading = false;

  int page = 1;

  bool isRefreshing = false;

  bool isLoadMoring = false;

  final RefreshController refreshController = new RefreshController();
  final List dataList = new List();

  final PullLoadWidgetControl pullLoadWidgetControl =
      new PullLoadWidgetControl();

  _lockToAwait() async {
    ///if loading, lock to await
    doDelayed() async {
      await Future.delayed(Duration(seconds: 1)).then((_) async {
        if (isLoading) {
          return await doDelayed();
        } else {
          return null;
        }
      });
    }

    await doDelayed();
  }

  showRefreshLoading() {
    new Future.delayed(const Duration(seconds: 0), () {
//      refreshIndicatorKey.currentState.show().then((e) {});
      return true;
    });
  }

  @protected
  resolveRefreshResult(res) {
    if (res != null && res.result) {
      pullLoadWidgetControl.dataList.clear();
      if (isShow) {
        setState(() {
          pullLoadWidgetControl.dataList.addAll(res.data);
        });
      }
    }
  }

  @protected
  Future<Null> handleRefresh() async {
    if (isLoading) {
      if (isRefreshing) {
        return null;
      }
      await _lockToAwait();
    }
    try {
      isLoading = true;
      isRefreshing = true;
      page = 1;
      var res = await requestRefresh();
      resolveRefreshResult(res);
      resolveDataResult(res);
      if (res != null && res.next != null) {
        var resNext = await res.next();
        resolveRefreshResult(resNext);
        resolveDataResult(resNext);
      }
      isLoading = false;
      isRefreshing = false;

      if (mounted)
        setState(() {
          refreshController.refreshCompleted();
        });
    } catch (e) {
      isLoading = false;
      isRefreshing = false;
      if (mounted) {
        setState(() {
          refreshController.refreshFailed();
        });
      }
    }
    return null;
  }

  @protected
  Future<Null> onLoadMore() async {
    if (isLoading) {
      if (isLoadMoring) {
        return null;
      }
      await _lockToAwait();
    }
    try {
      isLoading = true;
      isLoadMoring = true;
      page++;
      var res = await requestLoadMore();
      if (res != null && res.result) {
        if (isShow) {
          setState(() {
            pullLoadWidgetControl.dataList.addAll(res.data);
          });
        }
      }
      resolveDataResult(res);
      isLoading = false;
      isLoadMoring = false;
      if (res != null && res.data.length > 0) {
        refreshController.loadComplete();
      } else if (res != null && res.data.length == 0) {
        refreshController.loadNoData();
      } else {
        refreshController.loadFailed();
      }
    } catch (e) {
      isLoading = false;
      isLoadMoring = false;
      page--;
      if (isShow) {
        setState(() {
          refreshController.loadFailed();
        });
      }
    }
    return null;
  }

  @protected
  resolveDataResult(res) {
    // if (isShow) {
    //   setState(() {
    pullLoadWidgetControl.needLoadMore.value = (res != null &&
        res.data != null &&
        res.data.length == Config.PAGE_SIZE);
    //   });
    // }
  }

  @protected
  clearData() {
    if (isShow) {
      setState(() {
        pullLoadWidgetControl.dataList.clear();
      });
    }
  }

  ///下拉刷新数据
  @protected
  requestRefresh() async {}

  ///上拉更多请求数据
  @protected
  requestLoadMore() async {}

  ///是否需要第一次进入自动刷新
  @protected
  bool get isRefreshFirst;

  ///是否需要保持
  @override
  bool get wantKeepAlive => true;

  List get getDataList => dataList;

  getListItem(int i) => dataList[i];

  @override
  void initState() {
    isShow = true;
    super.initState();
    pullLoadWidgetControl.dataList = getDataList;
    if (pullLoadWidgetControl.dataList.length == 0 && isRefreshFirst) {
      handleRefresh();
      showRefreshLoading();
    }
  }

  @override
  void dispose() {
    isShow = false;
    isLoading = false;
    super.dispose();
  }
}
